package org.dtrevien;

import graphviz.api.GraphViz;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

import org.dtrevien.metamodel.graphviz.visitor.impl.DotLanguageGenerator;
import org.dtrevien.metamodel.java.Systeme;
import org.dtrevien.metamodel.java.visitor.impl.GraphvizConverter;
import org.dtrevien.yuml.parser.YumlEventListener;
import org.dtrevien.yuml.parser.YumlReader;
import org.dtrevien.yuml.parser.impl.YumlEventListenerImpl;

/**
 * Main application system
 * Use it to create and start graph generation routine from yUml to dot code to graphviz graph
 * 
 * @author davidtrevien
 *
 */
public class Application {

	private final File root = new File(".");
	private final File desk = new File(System.getProperty("user.home")+"/Desktop");
	public File dot;
	public File yuml;
	
	public Application() {
		this.dot = new File(this.root.getAbsolutePath()+"/gen.dot");
		this.yuml = new File(this.root.getAbsolutePath()+"/yuml");
	}
	
	/**
	 * Get the content of the given file
	 * 
	 * @param f the file
	 * @return
	 * @throws IOException
	 */
	public String getFileContent(final File f) throws IOException {
		StringBuilder text = new StringBuilder();
		String NL = System.getProperty("line.separator");
		Scanner scanner = new Scanner(new FileInputStream(f), "UTF-8");
		try {
			while (scanner.hasNextLine()) {
				text.append(scanner.nextLine() + NL);
			}
		} finally {
			scanner.close();
		}
		return text.toString();
	}
	
	/**
	 * Write Dot code content into the configured dot file
	 * 
	 * @param content
	 * @throws IOException
	 */
	public void writeDot(String content) throws IOException {
		BufferedWriter bw = null;
		try {
			this.dot.createNewFile();
			FileWriter fw = new FileWriter(this.dot);
			bw = new BufferedWriter(fw);
			bw.write(content);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			bw.close();
		}
	}
	
	/**
	 * Write yUml code content into the configured yuml file
	 * 
	 * @param content
	 * @throws IOException
	 */
	public void writeYUML(String content) throws IOException {
		BufferedWriter bw = null;
		try {
			this.yuml.createNewFile();
			FileWriter fw = new FileWriter(this.yuml);
			bw = new BufferedWriter(fw);
			bw.write(content);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			bw.close();
		}
	}
	
	/**
	 * Write all files on the user's Desktop
	 * (write an yuml, a dot and a graphviz file)
	 * @throws IOException 
	 */
	public void writeAllOnDesktop(String dir, String yumlContent) throws IOException {
		BufferedWriter bw = null;
		dir = dir.replace(" ", "").trim();
		try {
			File f = new File(this.desk.getAbsolutePath()+"/"+dir);
			f.mkdirs();
			
			//YUML
			f = new File(this.desk.getAbsolutePath()+"/"+dir+"/gen.yuml");
			f.createNewFile();
			FileWriter fw = new FileWriter(f);
			bw = new BufferedWriter(fw);
			bw.write(yumlContent);
			bw.close();
			
			//DOT
			f = new File(this.desk.getAbsolutePath()+"/"+dir+"/gen.dot");
			f.createNewFile();
			fw = new FileWriter(f);
			bw = new BufferedWriter(fw);
			bw.write(getFileContent(this.dot));
			bw.close();
			
			//GRAPHVIZ
			f = new File(this.desk.getAbsolutePath()+"/"+dir+"/graph.png");
			f.createNewFile();
			fw = new FileWriter(f);
			bw = new BufferedWriter(fw);
			GraphViz gv = new GraphViz();
			gv.add(getFileContent(this.dot));
			gv.writeGraphToFile( gv.getGraph( gv.getDotSource(), "png" ), f);
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			bw.close();
		}
	}
	
	/**
	 * Start routine
	 * 
	 * @throws Exception
	 */
	public void startApplication() throws Exception {
		YumlEventListener handler = new YumlEventListenerImpl();
		YumlReader reader = new YumlReader();
		reader.setHandler(handler);
		reader.parse(this.yuml);
		
		Systeme s = ((YumlEventListenerImpl)handler).getSysteme();
		
		//Graphviz meta model
		GraphvizConverter gconv = new GraphvizConverter();
		gconv.visiteSystem(s);
		
		//Dot Language generation
		DotLanguageGenerator dgen = new DotLanguageGenerator();
		dgen.visitGraphvizModel(gconv.getGraphvizModel());
		writeDot(dgen.getResult());
	}
	
	public File getDesktop() {
		return this.desk;
	}
	
	public String getFileExtention(File f) {
		String fileName = f.getName();
		String ext = "";
		int mid = fileName.lastIndexOf(".");
		ext = fileName.substring(mid + 1, fileName.length());
		return ext;
	}
	
	/**
	 * Restart routine
	 * @param f yuml file to read
	 * @throws Exception 
	 */
	public void restart(File f) throws Exception {
		this.yuml = f;
		startApplication();
	}
	
	/**
	 * Restart routine 
	 * 
	 * @param yuml yuml string to read
	 * @throws Exception
	 */
	public void restart(String yuml) throws Exception {
		writeYUML(yuml);
		startApplication();
	}
}
